home *** CD-ROM | disk | FTP | other *** search
/ Chip 1996 April / CHIP 1996 aprilis (CD06).zip / CHIP_CD06.ISO / sac / pack / unrar-st.lzh / UNRAR.C < prev    next >
C/C++ Source or Header  |  1995-02-09  |  23KB  |  996 lines

  1. /******    *****   ******
  2.  **   **  **   **  **   **      Utilidad unRAR versión 1.00e
  3.  ******   *******  ******       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4.  **   **  **   **  **   **       Versión portable y GRATUITA
  5.  **   **  **   **  **   **       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6.  
  7.      Código principal
  8.  
  9.    USTED PUEDE CAMBIAR EL SIGUIENTE CODIGO PARA
  10.    OBTENER MAYOR COMPATIBILIDAD CON SU SISTEMA OPERATIVO.
  11.  
  12.    POR FAVOR ENVIE CUALQUIER NOTA O MODIFICACION A
  13.    CUALQUIER CENTRO DE SOPORTE RAR (VEA RAR_BBS.TXT)
  14.    O DIRECTAMENTE AL CENTRO DE CONTACTO DEL AUTOR:
  15.  
  16.             andrey@vybor.chel.su
  17.            FIDOnet: Andrey Spasibozhko, 2:5010/23
  18.    CONTACTO POR VOZ   : +7-3512-130-231
  19.  
  20. */
  21.  
  22. #include "unrar.h"          /* definiciones */
  23. #include "unpack.c"         /* funciones de descompresión */
  24.  
  25. void   SplitCommandLine();  /* examina línea de comandos */
  26. int    CmpName();           /* comprueba máscara de fichero */
  27. char*  PointToName();       /* devuelve trayectoria */
  28. void   NextVolumeName();    /* busca nombre del siguiente volumen */
  29. void   SplitName();         /* descompone trayectoria */
  30. void   ExecuteCommand();    /* ejecuta orden externa */
  31. void   ListArchive();       /* lista contenido del archivo */
  32. int    ExtrFile();          /* extrae un solo fichero */
  33. void   Help();              /* visualiza ayuda sobre el uso */
  34. void   ShutDown();          /* suspende el trabajo */
  35. void   ErrExit();           /* acaba con código de error */
  36. void   CreatePath();        /* crea directorio */
  37. int    tread();             /* lee con verificación */
  38. void   tclose();            /* cierra con verificación */
  39. void   MergeArc();          /* al siguiente volumen */
  40. void   UnstoreFile();       /* extrae fichero no comprimido */
  41. int    IsArchive();         /* comprueba identificación de archivo RAR */
  42. void   CheckArc();          /* igual pero con salida */
  43. int    strnicomp();         /* compara cadenas */
  44. char*  strtolwr();          /* convierte cadena a minúsculas */
  45. int    ToPercent();         /* calcula percentaje */
  46. int    ReadBlock();         /* lee bloque del archivo */
  47. int    IsProcessFile();     /* debe ser procesado el fichero ? */
  48. int    UnpRead();           /* leer mientras extrae */
  49. int    UnpWrite();          /* escribe mientras extrae */
  50. void   InitCRC();           /* inicializa tabla del CRC */
  51. UDWORD CRC();               /* calcula CRC */
  52. #ifdef TOS
  53. void   wait_key();            /* espera a que se pulse una tecla */
  54. #endif
  55.  
  56. struct MarkHeader MarkHead;
  57. struct ArchiveHeader Mhd;
  58. struct FileHeader Lhd;
  59.  
  60. UDWORD CRC32_Table[256],UnpFileCRC;
  61. HPBYTE TmpMemory;
  62.  
  63. int ArgCount=0;
  64. char ArgNames[16][80],MainCommand;
  65. char CurExtrFile[80]={0},ArcName[80],ArcFileName[80],ExtrPath[80];
  66. int SolidType,UnpVolume,TestMode,ExitCode=0;
  67. #ifndef TOS
  68.   FILE *ArcFPtr=NULL,*FileFPtr=NULL,*RdUnpFPtr,*WrUnpFPtr;
  69. #else
  70.   int ArcHandler, FileHandler, RdUnpHandler, WrUnpHandler;
  71. #endif
  72. long NextBlockPos,UnpPackedSize;
  73.  
  74.  
  75. main(Argc,Argv)
  76. int Argc;
  77. char *Argv[];
  78. {
  79.   printf("\n UNRAR 1.00e versión freeware portable      (C) 1994 Eugene Roshal\n");
  80. #ifdef TOS
  81.   Cconws("\n\r");
  82.   Cconws(" -----------------------------------------------------------------\n\r");
  83.   Cconws(" Adaptación para ordenadores Atari┐ por: Luis Manuel Asensio Royo.\n\r");
  84.   Cconws(" Febrero de 1995, Barcelona (España).  >>>>> Motorola inside <<<<<\n\r");
  85.   Cconws(" -----------------------------------------------------------------\n\r");
  86. #endif
  87.   if ((TmpMemory=(HPBYTE)MEMALLOC(UNP_MEMORY))==NULL)
  88.     ErrExit(EMEMORY,MEMORY_ERROR);
  89.   MakeTbl();
  90.   SplitCommandLine(Argc,Argv);
  91.   ExecuteCommand();
  92.   ShutDown(SD_MEMORY);
  93.   exit(ExitCode);
  94. }
  95.  
  96.  
  97. int CmpName(Mask,Name)
  98. char *Mask;
  99. char *Name;
  100. {
  101.   while (1)
  102.   {
  103.     if (*Mask=='*')
  104.     {
  105.       while (*Mask!='.' && *Mask!=0)
  106.     Mask++;
  107.       while (*Name!='.' && *Name!=0)
  108.     Name++;
  109.     }
  110.     if (*Mask==0)
  111.       return(*Name==0);
  112.     if (*Name==0 && *Mask=='.')
  113.     {
  114.       Mask++;
  115.       continue;
  116.     }
  117.     if (toupper(*Mask)==toupper(*Name) || *Mask=='?' && *Name!=0)
  118.     {
  119.       Mask++;
  120.       Name++;
  121.     }
  122.     else
  123.       return(0);
  124.   }
  125. }
  126.  
  127.  
  128. void ErrExit(ErrCode,Code)
  129. int ErrCode;
  130. int Code;
  131. {
  132.   char ErrMsg[80];
  133.   switch(ErrCode)
  134.   {
  135.     case EEMPTY:
  136.       strcpy(ErrMsg,"");
  137.       break;
  138.     case EWRITE:
  139.       strcpy(ErrMsg,"Error de escritura. ¿ Disco lleno ?");
  140.       break;
  141.     case EREAD:
  142.       strcpy(ErrMsg,"Error de lectura");
  143.       break;
  144.     case EOPEN:
  145.       strcpy(ErrMsg,"Error al abrir fichero");
  146.       break;
  147.     case ECLOSE:
  148.       strcpy(ErrMsg,"Error al cerrar fichero");
  149.       break;
  150.     case EMEMORY:
  151.       strcpy(ErrMsg,"Memoria insuficiente");
  152.       break;
  153.     case EARCH:
  154.       strcpy(ErrMsg,"Archivo dañado");
  155.       break;
  156.   }
  157.   if (ErrCode!=EEMPTY)
  158.     printf("\n Programa abortado\n %s",ErrMsg);
  159.   ShutDown(SD_FILES | SD_MEMORY);
  160.   exit(Code);
  161. }
  162.  
  163.  
  164. void CreatePath(fpath)
  165. char *fpath;
  166. {
  167.   char *ChPtr;
  168.   ChPtr=fpath;
  169.   while(*ChPtr!=0 && (ChPtr=strchr(ChPtr,PATHDIV))!=NULL)
  170.   {
  171.     *ChPtr=0;
  172.     if (MAKEDIR(fpath)==0)
  173.       printf("\n Creando     %-49s",fpath);
  174.     *ChPtr=PATHDIV;
  175.     ChPtr++;
  176.   }
  177. }
  178.  
  179.  
  180. void NextVolumeName()
  181. {
  182.   char *ChPtr;
  183.   ChPtr=strrchr(ArcName,'.');
  184.   if (!isdigit(*(ChPtr+2)) || !isdigit(*(ChPtr+3)))
  185.     strcpy(ChPtr+2,"00");
  186.   else
  187.   {
  188.     ChPtr+=3;
  189.     while ((++(*ChPtr))=='9'+1)
  190.     {
  191.       if (*(ChPtr-1)=='.')
  192.       {
  193.     *ChPtr='A';
  194.     break;
  195.       }
  196.       else
  197.       {
  198.     *ChPtr='0';
  199.     ChPtr--;
  200.       }
  201.     }
  202.   }
  203. }
  204.  
  205.  
  206. void MergeArc(ShowFileName)
  207. int ShowFileName;
  208. {
  209.   int Ch;
  210. #ifndef TOS
  211.   tclose(ArcFPtr);
  212. #else
  213.   tclose(ArcHandler);
  214. #endif
  215.   NextVolumeName();
  216. #ifndef TOS
  217.   while ((ArcFPtr=fopen(ArcName,"r"))==NULL)
  218. #else
  219.   while ((ArcHandler=Fopen(ArcName, FO_READ))<6)
  220. #endif
  221.   {
  222.     printf("\n Se requiere disco con %s. ¿ Continuar ? ",ArcName);
  223.     Ch=getchar();
  224.     if (toupper(Ch)=='N')
  225.       ErrExit(EEMPTY,USER_BREAK);
  226.   }
  227.   if (MainCommand=='T')
  228.     printf("\n\n Verificando archivo %s",ArcName);
  229.   else
  230.     if (MainCommand!='P')
  231.       printf("\n\n Extrayendo de %s",ArcName);
  232.   CheckArc();
  233.   ReadBlock(FILE_HEAD);
  234.   if (ShowFileName)
  235.     printf("\n     ...     %-49s",ArcFileName);
  236.   UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
  237. #ifndef TOS
  238.   fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
  239. #else
  240.   Fseek(NextBlockPos-Lhd.PackSize, ArcHandler, FSEEK_SET);
  241. #endif
  242.   UnpPackedSize=Lhd.PackSize;
  243. #ifndef TOS
  244.   RdUnpFPtr=ArcFPtr;
  245. #else
  246.   RdUnpHandler=ArcHandler;
  247. #endif
  248. }
  249.  
  250.  
  251. void UnstoreFile()
  252. {
  253.   int Code;
  254.   while ( 1 )
  255.   {
  256.     if ((Code=UnpRead((UBYTE *)TmpMemory,0x7f00))==-1)
  257.       ErrExit(EWRITE,WRITE_ERROR);
  258.     if (Code==0)
  259.       break;
  260.     if (UnpWrite((UBYTE *)TmpMemory,(UWORD)Code)==-1)
  261.       ErrExit(EWRITE,WRITE_ERROR);
  262.   }
  263. }
  264.  
  265.  
  266. int IsArchive()
  267. {
  268.   UBYTE Mark[7],Header[13];
  269.   SolidType=0;
  270. #ifndef TOS
  271.   if (tread(ArcFPtr,Mark,7)!=7)
  272. #else
  273.   if (tread(ArcHandler, Mark, 7)!=7)
  274. #endif
  275.     return(0);
  276.   if (Mark[0]!=0x52 || Mark[1]!=0x61 || Mark[2]!=0x72 || Mark[3]!=0x21 ||
  277.       Mark[4]!=0x1a || Mark[5]!=0x07 || Mark[6]!=0x00)
  278.     return(0);
  279. #ifndef TOS
  280.   if (tread(ArcFPtr, Header,13) != 13)
  281. #else
  282.   if (tread(ArcHandler, Header, 13)!=13)
  283. #endif
  284.     return(0);
  285.   Mhd.HeadCRC  = Header[0]+(UWORD)Header[1]*0x100;
  286.   Mhd.HeadType = Header[2];
  287.   Mhd.Flags    = Header[3]+(UWORD)Header[4]*0x100;
  288.   Mhd.HeadSize = Header[5]+(UWORD)Header[6]*0x100;
  289.   if (!(Mhd.HeadCRC==(UWORD)~CRC(0xFFFFFFFFL,&Header[2],11)))
  290.     printf("\n Cabecera de archivo dañada");
  291.   SolidType=(Mhd.Flags & MHD_SOLID);
  292. #ifndef TOS
  293.   fseek(ArcFPtr, Mhd.HeadSize-13, SEEK_CUR);
  294. #else
  295.   Fseek(Mhd.HeadSize-13, ArcHandler, FSEEK_CUR);
  296. #endif
  297.   return(1);
  298. }
  299.  
  300.  
  301. void CheckArc()
  302. {
  303.   if (!IsArchive())
  304.   {
  305.     printf("\nArchivo incorrecto %s",ArcName);
  306.     ErrExit(EEMPTY,FATAL_ERROR);
  307.   }
  308. }
  309.  
  310.  
  311. #ifndef TOS
  312. int tread(FPtr,buf,len)
  313. FILE *FPtr;
  314. void *buf;
  315. unsigned len;
  316. #else
  317. int tread(int Handler, void *buf, unsigned len)
  318. #endif
  319. {
  320.   int Code;
  321. #ifndef TOS
  322.   Code=fread(buf, 1, len, FPtr);
  323. #else
  324.   Code=Fread(Handler, len, buf);
  325. #endif
  326.   if (Code==-1)
  327.     ErrExit(EREAD,FATAL_ERROR);
  328.   return(Code);
  329. }
  330.  
  331.  
  332. #ifndef TOS
  333. void tclose(FPtr)
  334. FILE *FPtr;
  335. #else
  336. void tclose(int Handler)
  337. #endif
  338. {
  339. #ifndef TOS
  340.   if (fclose(FPtr)==EOF)
  341. #else
  342.   if (Fclose(Handler)!=0)
  343. #endif
  344.     ErrExit(ECLOSE,FATAL_ERROR);
  345. }
  346.  
  347.  
  348. char* PointToName(Path)
  349. char *Path;
  350. {
  351.   char *ChPtr;
  352.   if ((ChPtr=strrchr(Path,PATHDIV))!=NULL)
  353.     return(ChPtr+1);
  354.   else
  355.     if ((ChPtr=strrchr(Path,':'))!=NULL)
  356.       return(ChPtr+1);
  357.     else
  358.       return(Path);
  359. }
  360.  
  361.  
  362. int strnicomp(Str1,Str2,MaxLen)
  363. char *Str1;
  364. char *Str2;
  365. int MaxLen;
  366. {
  367.   if (MaxLen==0)
  368.     return(0);
  369.   while (MaxLen-- > 0)
  370.   {
  371.     if (toupper(*Str1)!=toupper(*Str2))
  372.       return(1);
  373.     if (*Str1==0)
  374.       return(0);
  375.     Str1++;
  376.     Str2++;
  377.   }
  378.   return(0);
  379. }
  380.  
  381.  
  382. char* strtolwr(Str)
  383. char *Str;
  384. {
  385.   char *ChPtr;
  386.   for (ChPtr=Str;*ChPtr!=0;ChPtr++)
  387.     *ChPtr=tolower(*ChPtr);
  388.   return(Str);
  389. }
  390.  
  391.  
  392. void SplitName(Path,Dir,Name)
  393. char *Path;
  394. char *Dir;
  395. char *Name;
  396. {
  397.   char *ChPtr,*ChPtr1;
  398.   if ((ChPtr=strrchr(Path,':'))!=NULL)
  399.     ChPtr++;
  400.   else
  401.     ChPtr=Path;
  402.   if ((ChPtr1=strrchr(ChPtr,PATHDIV))!=NULL)
  403.   {
  404.     *ChPtr1=0;
  405.     strcpy(Dir,ChPtr);
  406.     *ChPtr1=PATHDIV;
  407.     ChPtr=ChPtr1+1;
  408.   }
  409.   else
  410.     *Dir=0;
  411.   strcpy(Name,ChPtr);
  412. }
  413.  
  414.  
  415. int ToPercent(N1,N2)
  416. long N1;
  417. long N2;
  418. {
  419.   if (N1 > 10000)
  420.   {
  421.     N1/=100;
  422.     N2/=100;
  423.   }
  424.   if (N2==0)
  425.     return(0);
  426.   if (N2<N1)
  427.     return(100);
  428.   return((int)(N1*100/N2));
  429. }
  430.  
  431.  
  432. void SplitCommandLine(Argc,Argv)
  433. int Argc;
  434. char *Argv[];
  435. {
  436.   int I,Len;
  437.  
  438.   ArgCount = MainCommand = *ArcName = *ExtrPath = 0;
  439.  
  440.   if (Argc==2)
  441.   {
  442.     MainCommand='X';
  443.     strcpy(ArcName,Argv[1]);
  444.   }
  445.   else
  446.     for (I=1;I<Argc;I++)
  447.     {
  448.       if (MainCommand==0)
  449.     MainCommand=toupper(Argv[I][0]);
  450.       else
  451.       {
  452.     if (*ArcName==0)
  453.       strncpy(ArcName,Argv[I],80);
  454.     else
  455.     {
  456.       Len=strlen(Argv[I]);
  457.       if (Len>0 && (Argv[I][Len-1]==':' || (Argv[I][Len-1]=='\\' || Argv[I][Len-1]=='/')))
  458.       {
  459.         strcpy(ExtrPath,Argv[I]);
  460.         ExtrPath[Len-1]=PATHDIV;
  461.       }
  462.       else
  463.         strncpy(ArgNames[(ArgCount++) & 0x0f],Argv[I],80);
  464.     }
  465.       }
  466.     }
  467.  
  468.   if (ArgCount==0 && *ArcName!=0)
  469.     strcpy(ArgNames[(ArgCount++) & 0x0f],"*.*");
  470.   if (strrchr(PointToName(ArcName),'.')==NULL)
  471.     strcat(ArcName,isupper(*ArcName) ? ".RAR":".rar");
  472.   ArgCount &= 0xF;
  473. }
  474.  
  475.  
  476. void ExecuteCommand()
  477. {
  478.   switch(MainCommand)
  479.   {
  480.     case 'E':
  481.     case 'X':
  482.     case 'T':
  483.       ExtrFile();
  484.       break;
  485.     case 'V':
  486.     case 'L':
  487.       ListArchive();
  488.       break;
  489.     case 0:
  490.       Help();
  491.       exit(0);
  492.     default:
  493.       Help();
  494.       exit(USER_ERROR);
  495.   }
  496. }
  497.  
  498. void ShutDown(Mode)
  499. int Mode;
  500. {
  501.   if (Mode & SD_FILES)
  502.   {
  503. #ifndef TOS
  504.     if (ArcFPtr!=NULL)
  505.       fclose(ArcFPtr);
  506.     if (FileFPtr!=NULL)
  507.       fclose(FileFPtr);
  508. #else
  509.     if (ArcHandler>5) Fclose(ArcHandler);
  510.     if (FileHandler>5) Fclose(FileHandler);
  511. #endif
  512.   }
  513.   if (Mode & SD_MEMORY)
  514.   {
  515.     if (TmpMemory!=NULL)
  516.       MEMFREE(TmpMemory);
  517.     printf("\n");
  518.   }
  519. }
  520.  
  521.  
  522. void Help()
  523. {
  524.   printf("\n Uso:     UNRAR <orden> <archivo> <ficheros...>\n");
  525.   printf("\n <Ordenes>\n");
  526.   printf("\n x       Extraer ficheros con subdirectorios");
  527.   printf("\n e       Extraer ficheros al directorio actual");
  528.   printf("\n t       Verificar ficheros del archivo");
  529.   printf("\n v       Lista extendida del archivo");
  530.   printf("\n l       Listar contenido del archivo");
  531.   printf("\n");
  532. #ifdef TOS
  533.   wait_key();
  534. #endif
  535. }
  536.  
  537.  
  538. int ExtrFile()
  539. {
  540.   char DestFileName[80];
  541.   long FileCount=0,TotalFileCount=0,DirCount=0,ErrCount=0;
  542.   int ExtrFile=0,Size,SkipSolid=0,UnpSolid;
  543.  
  544. #ifndef TOS
  545.   if ((ArcFPtr=fopen(ArcName,"r"))==NULL)
  546. #else
  547.   if ((ArcHandler=Fopen(ArcName, FO_READ))<6)
  548. #endif
  549.     ErrExit(EOPEN,FATAL_ERROR);
  550.  
  551.   CheckArc();
  552.   CreateEncTbl(TmpMemory);
  553.   UnpVolume=UnpSolid=0;
  554.   if (MainCommand=='T')
  555.     printf("\n Verificando archivo %s\n",ArcName);
  556.   else
  557.     printf("\n Extrayendo de %s\n",ArcName);
  558.  
  559.   while (1)
  560.   {
  561.     Size=ReadBlock(FILE_HEAD);
  562.  
  563.     if (Size<=0 && UnpVolume==0)
  564.       break;
  565.     if ((Lhd.Flags & LHD_SPLIT_BEFORE) && SolidType)
  566.     {
  567.       printf("\nArchivo sólido: se requiere el primer volumen");
  568.       ErrExit(EEMPTY,FATAL_ERROR);
  569.     }
  570.     if (UnpVolume && Size==0)
  571.       MergeArc(0);
  572.     UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
  573. #ifndef TOS
  574.     fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
  575. #else
  576.     Fseek(NextBlockPos-Lhd.PackSize, ArcHandler, FSEEK_SET);
  577. #endif
  578.  
  579.     TestMode=0;
  580.     ExtrFile=0;
  581.     SkipSolid=0;
  582.  
  583.     if (IsProcessFile(COMPARE_PATH) && (Lhd.Flags & LHD_SPLIT_BEFORE)==0
  584.     || (SkipSolid=SolidType)!=0)
  585.     {
  586.  
  587.       strcpy(DestFileName,ExtrPath);
  588.       strcat(DestFileName,(MainCommand!='E') ? ArcFileName : PointToName(ArcFileName));
  589.  
  590.       ExtrFile=!SkipSolid;
  591.  
  592.       if (Lhd.UnpVer<15 || Lhd.UnpVer>UNP_VER)
  593.       {
  594.     printf("\n %s: método desconocido",ArcFileName);
  595.     ExtrFile=0;
  596.     ErrCount++;
  597.     ExitCode=WARNING;
  598.       }
  599.  
  600.       if (Lhd.Flags & LHD_PASSWORD)
  601.       {
  602.     printf("\n %s: imposible procesar fichero encriptado",ArcFileName);
  603.     if (SolidType)
  604.       ErrExit(EEMPTY,FATAL_ERROR);
  605.     ExtrFile=0;
  606.     ErrCount++;
  607.     ExitCode=WARNING;
  608.       }
  609.  
  610.       if (Lhd.HostOS==MS_DOS && (Lhd.FileAttr & DOSFA_DIREC))
  611.       {
  612.     if (MainCommand=='E')
  613.       continue;
  614.     if (SkipSolid)
  615.     {
  616.       printf("\n Omitiendo   %-49s Correcto",ArcFileName);
  617.       continue;
  618.     }
  619.     if (MainCommand=='T')
  620.     {
  621.       printf("\n Verificando %-49s Correcto",ArcFileName);
  622.       continue;
  623.     }
  624.     CreatePath(DestFileName);
  625.     if (MAKEDIR(DestFileName)==0)
  626.       printf("\n Creando     %-49s",ArcFileName);
  627.     continue;
  628.       }
  629.       else
  630.       {
  631.     if (MainCommand=='T' && ExtrFile)
  632.       TestMode=1;
  633.     if ((MainCommand=='E' || MainCommand=='X') && ExtrFile)
  634.     {
  635.       CreatePath(DestFileName);
  636. #ifndef TOS
  637.       if ((FileFPtr=fopen(DestFileName,"w"))==NULL)
  638. #else
  639.       if ((FileHandler=Fcreate(DestFileName, 0))<5)
  640. #endif
  641.       {
  642.         printf("\n Imposible crear %s",DestFileName);
  643.         ExitCode=WARNING;
  644.         ExtrFile=0;
  645.       }
  646.     }
  647.       }
  648.  
  649.       if (!ExtrFile && SolidType)
  650.     SkipSolid=TestMode=ExtrFile=1;
  651.       if (ExtrFile)
  652.       {
  653.     TotalFileCount++;
  654.     if (SkipSolid)
  655.       printf("\n Omitiendo   %-49s",ArcFileName);
  656.     else
  657.     {
  658.       FileCount++;
  659.       switch(MainCommand)
  660.       {
  661.         case 'T':
  662.           printf("\n Verificando %-49s",ArcFileName);
  663.           break;
  664.         case 'X':
  665.         case 'E':
  666.           printf("\n Extrayendo  %-49s",DestFileName);
  667.           break;
  668.       }
  669.     }
  670.     strcpy(CurExtrFile,DestFileName);
  671.     UnpFileCRC=0xFFFFFFFFL;
  672.     UnpPackedSize=Lhd.PackSize;
  673.     DestUnpSize=Lhd.UnpSize;
  674. #ifndef TOS
  675.     RdUnpFPtr=ArcFPtr;
  676.     WrUnpFPtr=FileFPtr;
  677. #else
  678.     RdUnpHandler=ArcHandler;
  679.     WrUnpHandler=FileHandler;
  680. #endif
  681.     if (Lhd.Method==0x30)
  682.       UnstoreFile();
  683.     else
  684.       if (unpack(TmpMemory,UnpRead,UnpWrite,UnpSolid)==-1)
  685.         ErrExit(EWRITE,WRITE_ERROR);
  686.     if (TotalFileCount>0 && SolidType)
  687.       UnpSolid=1;
  688.     if (UnpFileCRC==~Lhd.FileCRC)
  689.     {
  690.       if (MainCommand!='P')
  691.         printf(" Correcto");
  692.     }
  693.     else
  694.     {
  695. #ifndef TOS
  696.       fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  697. #else
  698.       Fseek(NextBlockPos, ArcHandler, FSEEK_SET);
  699. #endif
  700.       printf("\n %-15s : fallo en el CRC",ArcFileName);
  701.       ExitCode=CRC_ERROR;
  702.       ErrCount++;
  703.     }
  704.     if (!TestMode)
  705.     {
  706.       SETFILETIME(FileFPtr,(void *)&Lhd.FileTime);
  707. #ifndef TOS
  708.       tclose(FileFPtr);
  709. #else
  710.       tclose(FileHandler);
  711. #endif
  712.     }
  713.     TestMode=0;
  714.     *CurExtrFile=0;
  715.       }
  716.     }
  717.     if (!ExtrFile && !SolidType)
  718. #ifndef TOS
  719.       fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  720. #else
  721.       Fseek(NextBlockPos, ArcHandler, FSEEK_SET);
  722. #endif
  723.   }
  724. #ifndef TOS
  725.   tclose(ArcFPtr);
  726. #else
  727.   tclose(ArcHandler);
  728. #endif
  729.   if ((FileCount+DirCount)==0)
  730.   {
  731.     printf("\n No hay ficheros");
  732.     ExitCode=WARNING;
  733.   }
  734.   else
  735.     if (ErrCount==0)
  736.       printf("\n  Todo correcto");
  737.     else
  738.       printf("\n  Total errores: %ld",ErrCount);
  739.   return(0);
  740. }
  741.  
  742.  
  743. void ListArchive()
  744. {
  745.   unsigned long TotalPackSize,TotalUnpSize,FileCount;
  746.   int I;
  747.   TotalPackSize=TotalUnpSize=FileCount=0;
  748. #ifndef TOS
  749.   if ((ArcFPtr=fopen(ArcName,"r"))==NULL)
  750. #else
  751.   if ((ArcHandler=Fopen(ArcName, FO_READ))<6)
  752. #endif
  753.     ErrExit(EOPEN,FATAL_ERROR);
  754.   CheckArc();
  755.   printf("\n ");
  756.   if (SolidType)
  757.     printf("Sólido ");
  758.   if (Mhd.Flags & MHD_MULT_VOL)
  759.     printf("%columen ",(SolidType) ? 'v':'V');
  760.   else
  761.     printf("%crchivo ",(SolidType) ? 'a':'A');
  762.   printf("%s\n",ArcName);
  763.   if (MainCommand=='V')
  764.     printf("\n Trayectoria/Comentario\n%12.12s","");
  765.   else
  766.     printf("\n Nombre     ");
  767.   printf("     Tamaño  Compr.  Ratio   Fecha  Hora  Atr.   CRC-32  Met. Ver\n");
  768.   for (I=0;I<77;I++)
  769.     printf("-");
  770.   while(ReadBlock(FILE_HEAD) > 0)
  771.   {
  772.     if (IsProcessFile(NOT_COMPARE_PATH))
  773.     {
  774.       printf("\n%c",(Lhd.Flags & LHD_PASSWORD) ? '*' : ' ');
  775.       if (MainCommand=='V')
  776.       {
  777.     printf("%-s",ArcFileName);
  778.     printf("\n%12s ","");
  779.       }
  780.       else
  781.     printf("%-12s",PointToName(ArcFileName));
  782.  
  783.       printf(" %8ld %8ld ",Lhd.UnpSize,Lhd.PackSize);
  784.       if (Lhd.Flags & (LHD_SPLIT_AFTER | LHD_SPLIT_BEFORE))
  785.     printf(" Split");
  786.       else
  787.     printf(" %3d%% ",ToPercent(Lhd.PackSize,Lhd.UnpSize));
  788.  
  789.       printf(" %02d-%02d-%02d %02d:%02d ",Lhd.FileTime.ft_day,
  790.          Lhd.FileTime.ft_month,(Lhd.FileTime.ft_year+1980)%100,
  791.          Lhd.FileTime.ft_hour,Lhd.FileTime.ft_min);
  792.  
  793.       if (Lhd.HostOS==MS_DOS)
  794.     printf("%c%c%c%c%c",
  795.       (Lhd.FileAttr & DOSFA_DIREC ) ? 'D' : '.',
  796.       (Lhd.FileAttr & DOSFA_RDONLY) ? 'R' : '.',
  797.       (Lhd.FileAttr & DOSFA_HIDDEN) ? 'H' : '.',
  798.       (Lhd.FileAttr & DOSFA_SYSTEM) ? 'S' : '.',
  799.       (Lhd.FileAttr & DOSFA_ARCH  ) ? 'A' : '.');
  800.       else
  801.     printf("     ");
  802.       printf(" %8.8lX  m%d  %d.%d",Lhd.FileCRC,Lhd.Method-0x30,Lhd.UnpVer/10,Lhd.UnpVer%10);
  803.       if (!(Lhd.Flags & LHD_SPLIT_BEFORE))
  804.       {
  805.     TotalUnpSize+=Lhd.UnpSize;
  806.     FileCount++;
  807.       }
  808.       TotalPackSize+=Lhd.PackSize;
  809.     }
  810. #ifndef TOS
  811.     fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  812. #else
  813.     Fseek(NextBlockPos, ArcHandler, FSEEK_SET);
  814. #endif
  815.   }
  816.   printf("\n");
  817.   for (I=0;I<77;I++)
  818.     printf("-");
  819.   printf("\n%5ld %16ld %8ld %4d%%\n",FileCount,TotalUnpSize,TotalPackSize,ToPercent(TotalPackSize,TotalUnpSize));
  820. #ifndef TOS
  821.   tclose(ArcFPtr);
  822. #else
  823.   Fclose(ArcHandler);
  824. #endif
  825. }
  826.  
  827.  
  828. int IsProcessFile(ComparePath)
  829. int ComparePath;
  830. {
  831.   int NumName,WildCards;
  832.   char ArgName[80],dir1[80],name1[15],dir2[80],name2[15];
  833.   for (NumName=0;NumName<ArgCount;NumName++)
  834.   {
  835.     memcpy((void *)ArgName,(void *)ArgNames[NumName],sizeof(ArgName));
  836.     WildCards=(strchr(ArgName,'?')!=NULL || strchr(ArgName,'*')!=NULL);
  837.     SplitName(ArgName,dir1,name1);
  838.     SplitName(ArcFileName,dir2,name2);
  839.     if (CmpName(name1,name2) && ((ComparePath==NOT_COMPARE_PATH && *dir1==0) ||
  840.       WildCards && strnicomp(dir1,dir2,strlen(dir1))==0 ||
  841.       strnicomp(dir1,dir2,1000)==0))
  842.       return(1);
  843.   }
  844.   return(0);
  845. }
  846.  
  847. int ReadBlock(BlockType)
  848. int BlockType;
  849. {
  850.   UDWORD HeadCRC;
  851.   UBYTE Header[32];
  852.   int Size,I;
  853.   memset(&Lhd,0,sizeof(Lhd));
  854.   memset(Header,0,sizeof(Header));
  855.   while (1)
  856.   {
  857. #ifndef TOS
  858.     Size=tread(ArcFPtr,Header,32);
  859. #else
  860.     Size=tread(ArcHandler, Header, 32);
  861. #endif
  862.     Lhd.HeadCRC  = Header[0] +(UWORD)Header[1]*0x100;
  863.     Lhd.HeadType = Header[2];
  864.     Lhd.Flags    = Header[3] +(UWORD)Header[4]*0x100;
  865.     Lhd.HeadSize = Header[5] +(UWORD)Header[6]*0x100;;
  866.     Lhd.PackSize = Header[7] +(UWORD)Header[8]*0x100+(UDWORD)Header[9]*0x10000L+(UDWORD)Header[10]*0x1000000L;
  867.     Lhd.UnpSize  = Header[11]+(UWORD)Header[12]*0x100+(UDWORD)Header[13]*0x10000L+(UDWORD)Header[14]*0x1000000L;
  868.     Lhd.HostOS   = Header[15];
  869.     Lhd.FileCRC  = Header[16]+(UWORD)Header[17]*0x100+(UDWORD)Header[18]*0x10000L+(UDWORD)Header[19]*0x1000000L;
  870.     *(UDWORD *)&Lhd.FileTime=Header[20]+(UWORD)Header[21]*0x100+(UDWORD)Header[22]*0x10000L+(UDWORD)Header[23]*0x1000000L;
  871.     Lhd.UnpVer   = Header[24];
  872.     Lhd.Method   = Header[25];
  873.     Lhd.NameSize = Header[26]+(UWORD)Header[27]*0x100;
  874.     Lhd.FileAttr = Header[28]+(UWORD)Header[29]*0x100+(UDWORD)Header[30]*0x10000L+(UDWORD)Header[31]*0x1000000L;
  875.     if (Size != 0 && (Size<7 || Lhd.HeadSize<7))
  876.       ErrExit(EARCH,FATAL_ERROR);
  877. #ifndef TOS
  878.     NextBlockPos=ftell(ArcFPtr)-Size+Lhd.HeadSize;
  879. #else
  880.     NextBlockPos=Fseek(0, ArcHandler, FSEEK_CUR)-Size+Lhd.HeadSize;
  881. #endif
  882.     if (Lhd.Flags & LONG_BLOCK)
  883.       NextBlockPos+=Lhd.PackSize;
  884.     if (Size==0 || BlockType==ALL_HEAD || Lhd.HeadType==BlockType)
  885.       break;
  886. #ifndef TOS
  887.     fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  888. #else
  889.     Fseek(NextBlockPos, ArcHandler, FSEEK_SET);
  890. #endif
  891.   }
  892.   if (Size>0 && BlockType==FILE_HEAD)
  893.   {
  894. #ifndef TOS
  895.     tread(ArcFPtr,ArcFileName,Lhd.NameSize);
  896. #else
  897.     tread(ArcHandler, ArcFileName, Lhd.NameSize);
  898. #endif
  899.     ArcFileName[Lhd.NameSize]=0;
  900.     Size+=Lhd.NameSize;
  901.     HeadCRC=CRC(0xFFFFFFFFL,&Header[2],30);
  902.     if (!(Lhd.HeadCRC==(UWORD)~CRC(HeadCRC,&ArcFileName[0],Lhd.NameSize)))
  903.       printf("\n %s: cabecera de fichero dañada\n",ArcFileName);
  904.     for (I=0;ArcFileName[I];I++)
  905.       if (ArcFileName[I]=='\\' || ArcFileName[I]=='/')
  906.     ArcFileName[I]=PATHDIV;
  907.     if (Lhd.HostOS==MS_DOS)
  908.       strtolwr(ArcFileName);
  909.   }
  910.   return(Size);
  911. }
  912.  
  913.  
  914. int UnpRead(Addr,Count)
  915. UBYTE *Addr;
  916. UWORD Count;
  917. {
  918.   int RetCode;
  919.   unsigned int ReadSize,TotalRead=0;
  920.   UBYTE *ReadAddr;
  921.   ReadAddr=Addr;
  922.   while (Count > 0)
  923.   {
  924.     ReadSize=(unsigned int)((Count>UnpPackedSize) ? UnpPackedSize : Count);
  925. #ifndef TOS
  926.     if ((RetCode=fread(ReadAddr,1,ReadSize,RdUnpFPtr))!=ReadSize)
  927. #else
  928.     if ((RetCode=Fread(RdUnpHandler, ReadSize, ReadAddr))!=ReadSize)
  929. #endif
  930.       break;
  931.     TotalRead+=RetCode;
  932.     ReadAddr+=RetCode;
  933.     Count-=RetCode;
  934.     UnpPackedSize-=RetCode;
  935.     if (UnpPackedSize == 0 && UnpVolume)
  936.       MergeArc(1);
  937.     else
  938.       break;
  939.   }
  940.   if (RetCode!=-1)
  941.     RetCode=(int)TotalRead;
  942.   return(RetCode);
  943. }
  944.  
  945.  
  946. int UnpWrite(Addr,Count)
  947. UBYTE *Addr;
  948. UWORD Count;
  949. {
  950.   int RetCode;
  951.   if (TestMode)
  952.     RetCode=(int)Count;
  953.   else
  954. #ifndef TOS
  955.     if ((RetCode=fwrite(Addr,1,Count,WrUnpFPtr))!=Count)
  956. #else
  957.     if ((RetCode=Fwrite(WrUnpHandler, Count, Addr))!=Count)
  958. #endif
  959.       RetCode = -1;
  960.   if (RetCode!=-1)
  961.     UnpFileCRC=CRC(UnpFileCRC,Addr,(UWORD)RetCode);
  962.   return(RetCode);
  963. }
  964.  
  965.  
  966. UDWORD CRC(StartCRC,Addr,Size)
  967. UDWORD StartCRC;
  968. UBYTE *Addr;
  969. UWORD Size;
  970. {
  971.   UWORD I;
  972.   if (!CRC32_Table[1])
  973.     InitCRC();
  974.   for (I=0;I<Size;I++)
  975.     StartCRC = CRC32_Table[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
  976.   return(StartCRC);
  977. }
  978.  
  979. void InitCRC()
  980. {
  981.   int I, J;
  982.   UDWORD C;
  983.   for (I=0;I<256;I++)
  984.   {
  985.     for (C=I,J=0;J<8;J++)
  986.       C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
  987.     CRC32_Table[I]=C;
  988.   }
  989. }
  990.  
  991. #ifdef TOS
  992.   void wait_key(void) {
  993.     Cconws("\n\r Pulsa cualquier tecla para continuar... ");
  994.     Bconin(2); /* Esperar pulsación del teclado. */
  995.   }
  996. #endif